 package com.ftwj.demo.permission.controller;
 
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Positive;

import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ftwj.demo.global.aop.Logger;
import com.ftwj.demo.global.aop.RateLimit;
import com.ftwj.demo.config.swagger.DataType;
import com.ftwj.demo.config.swagger.HttpMethod;
import com.ftwj.demo.config.swagger.ParamType;
import com.ftwj.demo.permission.entity.UserBean;
import com.ftwj.demo.permission.service.UserService;
import com.ftwj.demo.permission.vo.LoginEntity;
import com.ftwj.demo.permission.vo.UserBeanVo;
import com.ftwj.demo.global.shiro.ShiroPrincipal;
import com.ftwj.demo.global.shiro.ShiroUtil;
import com.ftwj.demo.utils.StringHelper;
import com.ftwj.demo.utils.captcha.ArithmeticCaptcha;
import com.ftwj.demo.utils.captcha.ChineseCaptcha;
import com.ftwj.demo.utils.captcha.GifCaptcha;
import com.ftwj.demo.utils.captcha.base.Captcha;
import com.ftwj.demo.utils.result.DataStateEnum;
import com.ftwj.demo.utils.result.MessageEnum;
import com.ftwj.demo.utils.result.ResultBean;
import com.ftwj.demo.utils.validate.ValidateUtil;

import cn.hutool.core.map.MapUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

/**
* 
* <p>Title: UserController</p>   
* <p>Description: 用户管理前端控制器</p>
* <p>Copyright: Copyright (c) 2020 </p>   
* <p>Company: 兰州飞天网景信息产业有限公司</p>    
* @author WangSLi
* @date 2020年2月13日 上午10:41:36
* @version V1.0
*/
@RestController
@RequestMapping("/user")
@Api(tags="用户管理接口", value="用户管理")
@Validated
public class UserController {

	@Autowired
	private UserService service;
	
	/**
	 * <p>Title: captcha</p>  
	 * <p>Description：获取验证码 </p>  
	 * @author WangSLi
	 * @date 2020年5月20日  
	 * @version 1.0
	 */
	@GetMapping("/captcha")
	@ApiOperation(value="验证码获取接口（DONE）", notes="备注",code=0,httpMethod="GET")
	@RateLimit
    public ResultBean<Map<String, Object>> captcha(HttpServletRequest request, HttpServletResponse response) throws Exception {
		//动态图
		//GifCaptcha gifCaptcha = new GifCaptcha(120, 30, 5,new Font("黑体",Font.BOLD, 26));
		//Map<String, Object> map = service.captcah(gifCaptcha);
		//中文
		//ChineseCaptcha chineseCaptcha = new ChineseCaptcha(120, 30, 3,new Font("黑体",Font.PLAIN, 26));
		//Map<String, Object> map = service.captcah(chineseCaptcha);
		//计算
		ArithmeticCaptcha arithmeticCaptcha = new ArithmeticCaptcha(150, 50, 3);
		arithmeticCaptcha.setFont(Captcha.FONT_1);
		Map<String, Object> map = service.captcah(arithmeticCaptcha);
		
		//SpringMVC 存入Session验证
		//CaptchaUtil.out(arithmeticCaptcha, request, response);
		//return ResultBean.success();
		
		return ResultBean.success(map); 
	}
	
	/**
	 * <p>Title: login</p>  
	 * <p>Description: 用户登录</p>  
	 * @param login
	 * @return 
	 * @author WangSLi
	 * @date 2020年5月20日  
	 * @version 1.0
	 */
	@PostMapping("/login")
	@ApiOperation(value="用户登录接口（DONE）", notes="备注",code=0,httpMethod="POST")
	@Logger //日志记录自定义注解
	/*
	@Captchar //Session验证时可用此注解实现验证码校验
	public ResultBean<?> login(@NotEmpty@RequestParam String username,@NotEmpty@RequestParam String password,@RequestParam(defaultValue="false") Boolean remember,@NotEmpty@RequestParam String captcha) {
		service.login(username, password, remember);
		return ResultBean.success();
	}
	*/
	public ResultBean<?> login(@Validated@RequestBody(required=true) LoginEntity login) {
		String token = service.login(login);
		return ResultBean.success(MapUtil.of("token", token));
	}
	
	/**
	 * 
	 * <p>Title: logout</p>  
	 * <p>Description: 用户登出</p>  
	 * @return 
	 * @author WangSLi
	 * @date 2020年5月20日  
	 * @version 1.0
	 */
	@PostMapping("/logout")
	@ApiOperation(value="用户退出接口（DONE）", notes="备注",code=0,httpMethod="POST")
	@Logger //日志记录自定义注解
	public ResultBean<?> logout() {
		service.logout();
		return ResultBean.success();
	}
	
	@PutMapping("/password")
	@ApiOperation(value="用户密码修改接口（DONE）", notes="备注",code=0,httpMethod="PUT")
	@ApiImplicitParams({
		@ApiImplicitParam(name="username", value="用户登录名（手机号）", dataType=DataType.STRING, paramType=ParamType.QUERY),
		@ApiImplicitParam(name="oldPasssword", value="旧密码", dataType=DataType.STRING, paramType=ParamType.QUERY),
		@ApiImplicitParam(name="newPasssword", value="新密码", dataType=DataType.STRING, paramType=ParamType.QUERY)
	})
	@Logger //日志记录自定义注解
	public ResultBean<?> changePassword(@RequestParam(name="username",required=false)String userName,@RequestParam(required=true) String oldPasssword, 
			@RequestParam(required=true)@Pattern(regexp=ValidateUtil.REGEX_PASSWORD,message="密码必须为6~18的数字字母组合") String newPasssword) {
		if(service.updatePassword(userName,oldPasssword,newPasssword)) {
			return ResultBean.success();
		}else {
			return ResultBean.error(MessageEnum.SERVER_FAILED);
		}
	}
	/**
	 * 
	 * <p>Title: register</p>  
	 * <p>Description: 用户注册</p>  
	 * @param user
	 * @return 
	 * @author WangSLi
	 * @date 2020年5月20日  
	 * @version 1.0
	 */
	//如果是 POST PUT 这种带 @RequestBody 的可以不用写  @ApiImplicitParam
	/*
	@PostMapping("/register")
	@ApiOperation(value="用户注册（DONE）", notes="备注",code=0,httpMethod="POST")
	public ResultBean<?> register(@RequestBody(required=true)@Validated UserBean user) {
		if(service.register(user)) {
			return ResultBean.success();
		} else {
			return ResultBean.error(MessageEnum.SERVER_FAILED);
		}
	}
	*/
	
	/**
	 * <p>Title: insert</p>  
	 * <p>Description: 管理员用户添加</p>  
	 * @param user
	 * @return 
	 * @author WangSLi
	 * @date 2020年5月20日  
	 * @version 1.0
	 */
	//如果是 POST PUT 这种带 @RequestBody 的可以不用写  @ApiImplicitParam
	@PostMapping("/insert")
	@ApiOperation(value="管理员添加用户（DONE）", notes="备注",code=0,httpMethod="POST")
	@Logger
	//@RequiresPermissions(value={"user:add"},logical=Logical.OR)
	public ResultBean<?> insert(@RequestBody(required=true)@Validated UserBean user) {
		if(service.insert(user.getPhone(),user.getShowName())) {
			return ResultBean.success();
		} else {
			return ResultBean.error(MessageEnum.SERVER_FAILED);
		}
	}
	
	/**
	 * <p>Title: reset</p>  
	 * <p>Description: 重置密码 </p>  
	 * @param id
	 * @return 
	 * @author WangSLi
	 * @date 2020年5月20日  
	 * @version 1.0
	 */
	@PutMapping("/reset/{id}")
	@ApiOperation(value="管理员重置用户密码（DONE）", notes="备注",code=0,httpMethod="PUT")
	@Logger
	//@RequiresPermissions(value={"user:reset"},logical=Logical.OR)
	@ApiImplicitParams({
		@ApiImplicitParam(name="id", value="用户编号", dataType=DataType.INTEGER, paramType=ParamType.PATH)
	})
	public ResultBean<?> reset(@PathVariable@Positive Integer id) {
		if(service.reset(id)) {
			return ResultBean.success();
		} else {
			return ResultBean.error(MessageEnum.SERVER_FAILED);
		}
	}
	
	/**
	 * <p>Title: disable</p>  
	 * <p>Description: 用户禁用</p>  
	 * @param id
	 * @author HeYang
	 * @date 2020年5月7日  
	 * @version 1.0
	 */
	@PutMapping("/operate/{operate}/{id}")
	@ApiOperation(value="账户逻辑禁用，恢复，删除（DONE）", notes="备注",code=0,httpMethod="PUT")
	@ApiImplicitParams({
		@ApiImplicitParam(name="id", value="操作类型（disabled:禁用，normal:恢复，delete:删除）", dataType=DataType.INTEGER, paramType=ParamType.PATH),
		@ApiImplicitParam(name="id", value="用户编号", dataType=DataType.INTEGER, paramType=ParamType.PATH)
	})
	@Logger //日志记录自定义注解
	public ResultBean<?> disable(@PathVariable String operate,@PathVariable@Positive(message="ID必须为不小于0的数字") Integer id) {
		Integer state = DataStateEnum.valueOf(operate.toUpperCase()).getCode();
		if(service.updateStateById(id,state)) {
			return ResultBean.success();
		} else {
			return ResultBean.error(MessageEnum.SERVER_FAILED);
		}
	}
	
	@GetMapping({"/info","/info/{id}"})
	@ApiOperation(value="用户信息（DONE）", notes="备注",code=0,httpMethod=HttpMethod.GET)
	@ApiImplicitParams({
		@ApiImplicitParam(name="id", value="用户编号", dataType=DataType.INTEGER, paramType=ParamType.PATH, required=false)
	})
	@RequiresAuthentication //已被系统认证的用户采用调用此方法
	public ResultBean<UserBean> info(@PathVariable(required=false) Integer id){
		UserBean data = service.getInfoById(id!=null?id:ShiroUtil.getUserId());
		return ResultBean.success(data);
	}
	
	@PutMapping("/update")
	@ApiOperation(value="用户信息修改（DONE）", notes="备注",code=0,httpMethod="PUT")
	@Logger //日志记录自定义注解
	public ResultBean<?> update(@RequestBody@Validated UserBeanVo bean) {
		if(service.updateVoById(bean)) {
			return ResultBean.success();
		} else {
			return ResultBean.error(MessageEnum.SERVER_FAILED);
		}
	}
	
	//如果你不想写 @ApiImplicitParam 那么 swagger 也会使用默认的参数名作为描述信息
	@GetMapping("/page")
	@ApiOperation(value="分页列表条件查询（DONE）", notes="备注",code=0, httpMethod="GET")
    @ApiImplicitParams({
    	@ApiImplicitParam(name="current", value="当前页数", dataType=DataType.INTEGER, paramType=ParamType.QUERY, defaultValue="1")
    	,@ApiImplicitParam(name="size", value="每页显示条数", dataType=DataType.INTEGER, paramType=ParamType.QUERY, defaultValue="10")
    	,@ApiImplicitParam(name="showname", value="用户名", dataType=DataType.STRING, paramType=ParamType.QUERY, required=false)
    	,@ApiImplicitParam(name="phone", value="手机号码（登录名）", dataType=DataType.STRING, paramType=ParamType.QUERY, required=false)
    	,@ApiImplicitParam(name="state", value="用户状态", dataType=DataType.INTEGER, paramType=ParamType.QUERY, required=false)
    })
	@RequiresAuthentication //已被系统认证的用户采用调用此方法
	public ResultBean<?> page(@RequestParam(defaultValue="1")@Positive Integer current, @RequestParam(defaultValue="10")@Positive Integer size,@RequestParam(name="showname",required=false) String showName,String phone,Integer state) {
		
		IPage<UserBean> page=new Page<UserBean>(current, size);
		UserBean bean=new UserBean();
		bean.setShowName(StringHelper.trim(showName));
		bean.setPhone(StringHelper.trim(phone));
		bean.setState(state);
		
		IPage<Map<String, Object>> data = service.pageMaps(page, bean);
		return ResultBean.success(data);
	}
	
	@GetMapping("/list")
	@ApiOperation(value="列表条件查询（DONE）", notes="备注",code=0, httpMethod=HttpMethod.GET)
    @ApiImplicitParams({
    	@ApiImplicitParam(name="showname", value="用户名", dataType=DataType.STRING, paramType=ParamType.QUERY, required=false)
    	,@ApiImplicitParam(name="phone", value="手机号码（登录名）", dataType=DataType.STRING, paramType=ParamType.QUERY, required=false)
    })
	@RequiresAuthentication
	public ResultBean<?> list(@RequestParam(name="showname",required=false) String showName,String phone) {
		UserBean bean=new UserBean();
		bean.setShowName(showName);
		bean.setPhone(phone);
		
		List<Map<String, Object>> data = service.listMaps(bean);
		return ResultBean.success(data);
	}
	
	@GetMapping("/principal")
	@ApiOperation(value="根据用户ID获取角色和权限", notes="备注",code=0,httpMethod="GET")
	@RequiresAuthentication
	public ResultBean<?> getShiroPrincipal(){
		ShiroPrincipal principal = service.getShiroPrincipal();
		return ResultBean.success(principal);
	}
	
	/**
	 *	为用户配置角色
	 */
	@PutMapping("/config/roles")
	@ApiOperation(value="给用户配置角色", notes="备注",code=0,httpMethod="PUT")
	@RequiresRoles(value={"CJGLY","XTGLY","ZCXY"},logical=Logical.OR)
	public ResultBean<?> configRoles(@RequestParam(required=false) Integer userId, @RequestParam(name="roles") Integer[] roleIds){
		return ResultBean.success();
	}
	
}
